package com.wutianyi.module.dao.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.apache.commons.collections.CollectionUtils;

import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Query.FilterOperator;
import com.google.appengine.api.datastore.Text;
import com.wutianyi.module.commons.Item;
import com.wutianyi.module.commons.Pair;
import com.wutianyi.module.dao.ItemDao;
import com.wutianyi.utils.Utils;

import static com.wutianyi.entity.EntityTypeEnum.Item;
import static com.wutianyi.entity.EntityTypeEnum.Pair;
import static com.wutianyi.entity.DataStoreField.DS_P_VALUE;
import static com.wutianyi.entity.DataStoreField.DS_P_IID;
import static com.wutianyi.entity.DataStoreField.DS_P_GID;

/**
 * @author hanjiewu
 * 
 */
public class ItemDaoDataStoreImpl implements ItemDao {
	
	private static DatastoreService datastoreService = DatastoreServiceFactory
			.getDatastoreService();
	
	@Override
	public void insertItem(Item item) {
		Entity entity = new Entity(Item.name(), item.hashCode());
		entity.setProperty(DS_P_VALUE, new Text(Utils.serialize(item)));
		entity.setProperty(DS_P_GID, item.getgId());
		
		List<Entity> entities = new ArrayList<Entity>();
		entities.add(entity);
		
		if (null != item.getProperties()) {
			int iId = item.hashCode();
			int order = 1;
			for (Pair pair : item.getProperties()) {
				pair.setiId(iId);
				pair.setOrder(order);
				int id = pair.hashCode();
				Entity pEntity = new Entity(Pair.name(), id);
				pEntity.setProperty(DS_P_VALUE, Utils.serialize(pair));
				pEntity.setProperty(DS_P_IID, iId);
				entities.add(pEntity);
				pair.setId(id);
			}
		}
		item.setId(item.hashCode());
		item.setGmtModified(new Date());
		datastoreService.put(entities);
	}
	
	@Override
	public void insertItems(List<Item> items, int gId) {
		if (CollectionUtils.isEmpty(items)) {
			return;
		}
		for (Item item : items) {
			item.setgId(gId);
			insertItem(item);
		}
	}
	
	@Override
	public int updateItem(Item item) {
		Entity entity = new Entity(Item.name(), item.getId());
		entity.setProperty(DS_P_VALUE,  new Text(Utils.serialize(item)));
		entity.setProperty(DS_P_GID, item.getgId());
		
		List<Entity> entities = new ArrayList<Entity>();
		entities.add(entity);
		
		if (null != item.getProperties()) {
			int iId = item.hashCode();
			int order = 1;
			for (Pair pair : item.getProperties()) {
				pair.setiId(iId);
				pair.setOrder(order);
				Entity pEntity = new Entity(Pair.name(), pair.getId());
				pEntity.setProperty(DS_P_VALUE, Utils.serialize(pair));
				pEntity.setProperty(DS_P_IID, iId);
				entities.add(pEntity);
			}
		}
		item.setGmtModified(new Date());
		datastoreService.put(entities);
		return 1;
	}
	
	@Override
	public void updateItems(List<Item> items) {
		if (CollectionUtils.isEmpty(items)) {
			return;
		}
		for (Item item : items) {
			updateItem(item);
		}
	}
	
	@Override
	public List<Item> listItemsByGId(int gId) {
		Query query = new Query(Item.name());
		query.addFilter(DS_P_GID, FilterOperator.EQUAL, gId);
		Iterable<Entity> iters = datastoreService.prepare(query).asIterable();
		List<Item> items = new ArrayList<Item>();
		
		for (Entity entity : iters) {
			Item item = (Item) Utils.unSerialize(entity.getProperty(DS_P_VALUE));
			item.setId((int) entity.getKey().getId());
			items.add(item);
			item.setProperties(listPairByIId(item.getId()));
		}
		
		return items;
	}
	
	private List<Pair> listPairByIId(int iId) {
		Query query = new Query(Pair.name());
		query.addFilter(DS_P_IID, FilterOperator.EQUAL, iId);
		Iterable<Entity> iters = datastoreService.prepare(query).asIterable();
		List<Pair> pairs = new ArrayList<Pair>();
		for (Entity entity : iters) {
			Pair pair = (Pair) Utils.unSerialize(entity.getProperty(DS_P_VALUE));
			pair.setId((int) entity.getKey().getId());
			pairs.add(pair);
		}
		return pairs;
		
	}
}
